\begin{Exercise}[title={Channel},difficulty=1]
\label{ex:channels}
\Question\label{ex:channels q1} 修改在练习 Q\ref{ex:for-loop} 中创建的程序，
换句话说，主体中调用的函数现在是一个 goroutine 并且使用 channel 通讯。
不用担心 goroutine 是如何停止的。

\Question\label{ex:channels q2} 在完成了问题 \ref{ex:channels q1} 后，仍有一些待解决的问题。
其中一个麻烦是 goroutine 在 \func{main.main()} 结束的时候，没有进行清理。
更糟的是，由于 \func{main.main()} 和 \func{main.shower()} 的竞争关系，不是所有数字都被打印了。
本应该打印到 9，但是有时只打印到 8。添加第二个退出 channel，可以解决这两个问题。试试吧。
\footnote{需要用到 \func{select} 语句。}

\end{Exercise}

\begin{Answer}
\Question 程序可能的形式是： 
\lstinputlisting[label=go-chan,caption=Go 的 channel,numbers=right]{ex-channels/src/for-chan.go}
以通常的方式开始，在第 6 行创建了一个新的 int 类型的 channel。下一行调用了
\func{shower} 函数，用 \prog{ch} 变量作为参数，这样就可以与其通讯。然后进入 for 循环（第 8-10 行），
在循环中发送（通过 \lstinline{<-}）数字到函数（现在是 goroutine）\func{shower}。
在函数 \func{shower} 中等待（阻塞方式），直到接收到了数字（第 15 行）。
每个收到的数字都被打印（第 16 行）出来，然后继续第 14 行开始的死循环。

\Question 答案是
\lstinputlisting[label=go-quit-chan,caption=添加额外的退出 channel,numbers=right]{ex-channels/src/for-quit-chan.go}
在第 20 行从退出 channel 读取并丢弃该值。可以使用 \lstinline{q := <-quit}，
但是可能只需要用这个变量一次——在 Go 中是非法的。另一种办法，你可能已经想到了：
\lstinline{_ = <-quit}。在 Go 中这是合法的，但是第 20 行的形式在 Go 中更好。
\end{Answer}
